'use client'

import { useMemo } from 'react'
import type { SubBlockConfig } from '@/blocks/types'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'

type DependsOnConfig = string[] | { all?: string[]; any?: string[] }

/**
 * Parses dependsOn config and returns normalized all/any arrays
 */
function parseDependsOn(dependsOn: DependsOnConfig | undefined): {
  allFields: string[]
  anyFields: string[]
  allDependsOnFields: string[]
} {
  if (!dependsOn) {
    return { allFields: [], anyFields: [], allDependsOnFields: [] }
  }

  if (Array.isArray(dependsOn)) {
    // Simple array format: all fields required (AND logic)
    return { allFields: dependsOn, anyFields: [], allDependsOnFields: dependsOn }
  }

  // Object format with all/any
  const allFields = dependsOn.all || []
  const anyFields = dependsOn.any || []
  return {
    allFields,
    anyFields,
    allDependsOnFields: [...allFields, ...anyFields],
  }
}

/**
 * Centralized dependsOn gating for sub-block components.
 * - Computes dependency values from the active workflow/block
 * - Returns a stable disabled flag to pass to inputs and to guard effects
 * - Supports both AND (all) and OR (any) dependency logic
 */
export function useDependsOnGate(
  blockId: string,
  subBlock: SubBlockConfig,
  opts?: { disabled?: boolean; isPreview?: boolean; previewContextValues?: Record<string, any> }
) {
  const disabledProp = opts?.disabled ?? false
  const isPreview = opts?.isPreview ?? false
  const previewContextValues = opts?.previewContextValues

  const activeWorkflowId = useWorkflowRegistry((s) => s.activeWorkflowId)

  // Parse dependsOn config to get all/any field lists
  const { allFields, anyFields, allDependsOnFields } = useMemo(
    () => parseDependsOn(subBlock.dependsOn),
    [subBlock.dependsOn]
  )

  // For backward compatibility, expose flat list of all dependency fields
  const dependsOn = allDependsOnFields

  const normalizeDependencyValue = (rawValue: unknown): unknown => {
    if (rawValue === null || rawValue === undefined) return null

    if (typeof rawValue === 'object') {
      if (Array.isArray(rawValue)) {
        if (rawValue.length === 0) return null
        return rawValue.map((item) => normalizeDependencyValue(item))
      }

      const record = rawValue as Record<string, any>
      if ('value' in record) {
        return normalizeDependencyValue(record.value)
      }
      if ('id' in record) {
        return record.id
      }

      return record
    }

    return rawValue
  }

  // Get values for all dependency fields (both all and any)
  const dependencyValuesMap = useSubBlockStore((state) => {
    if (allDependsOnFields.length === 0) return {} as Record<string, unknown>

    // If previewContextValues are provided (e.g., tool parameters), use those first
    if (previewContextValues) {
      const map: Record<string, unknown> = {}
      for (const key of allDependsOnFields) {
        map[key] = normalizeDependencyValue(previewContextValues[key])
      }
      return map
    }

    if (!activeWorkflowId) {
      const map: Record<string, unknown> = {}
      for (const key of allDependsOnFields) {
        map[key] = null
      }
      return map
    }

    const workflowValues = state.workflowValues[activeWorkflowId] || {}
    const blockValues = (workflowValues as any)[blockId] || {}
    const map: Record<string, unknown> = {}
    for (const key of allDependsOnFields) {
      map[key] = normalizeDependencyValue((blockValues as any)[key])
    }
    return map
  })

  // For backward compatibility, also provide array of values
  const dependencyValues = useMemo(
    () => allDependsOnFields.map((key) => dependencyValuesMap[key]),
    [allDependsOnFields, dependencyValuesMap]
  ) as any[]

  const isValueSatisfied = (value: unknown): boolean => {
    if (value === null || value === undefined) return false
    if (typeof value === 'string') return value.trim().length > 0
    if (Array.isArray(value)) return value.length > 0
    return value !== ''
  }

  const depsSatisfied = useMemo(() => {
    // Check all fields (AND logic) - all must be satisfied
    const allSatisfied =
      allFields.length === 0 || allFields.every((key) => isValueSatisfied(dependencyValuesMap[key]))

    // Check any fields (OR logic) - at least one must be satisfied
    const anySatisfied =
      anyFields.length === 0 || anyFields.some((key) => isValueSatisfied(dependencyValuesMap[key]))

    return allSatisfied && anySatisfied
  }, [allFields, anyFields, dependencyValuesMap])

  // Block everything except the credential field itself until dependencies are set
  const blocked =
    !isPreview && allDependsOnFields.length > 0 && !depsSatisfied && subBlock.type !== 'oauth-input'

  const finalDisabled = disabledProp || isPreview || blocked

  return {
    dependsOn,
    dependencyValues,
    depsSatisfied,
    blocked,
    finalDisabled,
  }
}
